#include <QCoreApplication>
#include "generator.h"
#include "asyncgenerator.h"
#include "task.h"
#include "timerawaiter.h"
using namespace CCoroutine;

//定时器测试，在等待定时器定时完成后输出结果
class TimerTest:public Task<int>
{
public:
    coro_begin;
    //设置定时器时长然后开始计时
    qDebug()<<"定时器测试";
    timer.setInterval(1000);
    timer.setSingleShot(true);
    timer.start();

    coro_await(timer);//等待定时结束
    //输出结果
    qDebug()<<"定时结束";
    coro_return_value(2000)
    coro_end;
private:
    QTimer timer;//由于是无栈协程，因此协程体内部不能出现局部变量
};

//生成器测试，持续的生成数据
class GeneratorTest:public Generator<int,int>
{
public:
    coro_begin;
    qDebug()<<"生成器测试";
    for(index = 0;index < std::get<0>(args);index++)
    {
        current *= 2;
        coro_yield(current);//向外界输出数据
    }
    coro_end;

private:
    int current = 1;
    int index = 0;
};

//异步生成器，能够持续的生成数据的同时还能等待异步对象
class AsyncGeneratorTest:public AsyncGenerator<int,int>
{
public:
    coro_begin;
    qDebug()<<"异步生成器测试";
    timer.setInterval(1000);
    timer.setSingleShot(true);


    for(index = 0;index < std::get<0>(args);index++)
    {
        timer.start();
        coro_await(timer);//等待定时器
        current *= 2;
        coro_yield(current);//向外界输出数据
    }
    coro_end;

private:
    int current = 1;
    int index = 0;
    QTimer timer;
};


class test:public Task<int>
{
public:
    coro_begin;

    //TimerTest
    timerTest = createCoro<TimerTest>();
    coro_await(timerTest);
    qDebug()<<timerTest.result();

    //GeneratorTest
    for(auto i:createCoro<GeneratorTest>(10))
    {
        qDebug()<<"generated"<<i;
    }

    //AsyncGeneratorTest
    //想要使用异步生成器必须保存它的句柄,并且使用特殊的循环语句，目前没有更好的方法
    async_gen = createCoro<AsyncGeneratorTest>(4);
    async_for_begin(async_gen)
        qDebug()<<"generated"<<async_gen.value();
    async_for_end
    coro_end;
private:
    TimerTest::Controller timerTest;
    AsyncGeneratorTest::Controller async_gen;
};

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    //在普通函数内可以通过then函数在协程完成后执行相关操作
    createCoro<test>().getTask()->then<int>([=](int i)->int{
        qDebug()<<"测试结束";
        return 0;
    }).getTask()->then<int>([=](int i)->int{
        qDebug()<<"测试结束2";
        return 0;
    });
    return app.exec();
}
